import { ref, reactive } from 'vue';
import { showToast, showDialog } from 'vant';
import router from '@/router';
import { user } from '@/api';
import sessionManager, { saveUserInfo, clearSession, isLoggedIn as checkLoginStatus, getUserAddress } from '@/utils/auth/sessionManager';

// Web3 状态管理
const web3State = reactive({
  isConnected: false,
  account: '',
  chainId: '',
  provider: null,
  web3: null,
  networkName: ''
});


// 错误信息
const errorMessages = {
  noProvider: '未检测到MetaMask钱包，请安装MetaMask插件',
  userRejected: '用户拒绝了连接请求',
  alreadyConnected: '钱包已连接',
  connectionFailed: '连接钱包失败',
  signFailed: '签名失败',
  transactionFailed: '交易失败',
  wrongNetwork: '请切换到正确的网络'
};

// 网络配置
const networks = {
  1: { name: 'Ethereum Mainnet', symbol: 'ETH' },
  56: { name: 'Binance Smart Chain', symbol: 'BNB' },
  137: { name: 'Polygon Mainnet', symbol: 'MATIC' },
  42161: { name: 'Arbitrum One', symbol: 'ETH' },
  10: { name: 'Optimism', symbol: 'ETH' },
  // 添加更多网络...
};

/**
 * 检查是否安装了MetaMask
 * @returns {boolean} 是否存在MetaMask提供者
 */
const checkIfMetaMaskInstalled = () => {
  return window.ethereum !== undefined;
};

/**
 * 初始化Web3
 * @returns {Promise<boolean>} 初始化是否成功
 */
const initWeb3 = async () => {
  try {
    if (!checkIfMetaMaskInstalled()) {
      showDialog({
        title: '未检测到钱包',
        message: '您需要安装MetaMask钱包来使用此功能。是否前往安装？',
        confirmButtonText: '前往安装',
        cancelButtonText: '取消',
        showCancelButton: true
      }).then(action => {
        if (action === 'confirm') {
          window.open('https://metamask.io/download.html', '_blank');
        }
      });
      return false;
    }

    // 设置提供者
    web3State.provider = window.ethereum;
    
    // 监听账户变化
    window.ethereum.on('accountsChanged', handleAccountsChanged);
    
    // 监听链变化
    window.ethereum.on('chainChanged', handleChainChanged);
    
    // 监听连接
    window.ethereum.on('connect', handleConnect);
    
    // 监听断开连接
    window.ethereum.on('disconnect', handleDisconnect);

    // 尝试获取当前连接的账户
    const accounts = await window.ethereum.request({ method: 'eth_accounts' });
    if (accounts.length > 0) {
      handleAccountsChanged(accounts);
      return true;
    }
    
    return false;
  } catch (error) {
    console.error('初始化Web3失败:', error);
    return false;
  }
};

/**
 * 处理账户变化
 * @param {Array} accounts 账户列表
 */
const handleAccountsChanged = async (accounts) => {
  if (accounts.length === 0) {
    // 用户断开了所有账户
    web3State.isConnected = false;
    web3State.account = '';
    
    // 检查是否已登录
    if (checkLoginStatus()) {
      // 如果已登录，提示用户钱包已断开但不自动登出
      showToast('钱包已断开连接，登录状态保持不变');
    } else {
      showToast('钱包已断开连接');
    }
  } else {

    // 获取新账户
    const newAccount = accounts[0];
    
    // 检查是否与当前登录账户不同
    const isUserLoggedIn = checkLoginStatus();
    const loggedInAddress = getUserAddress();
    
    if (isUserLoggedIn && loggedInAddress && loggedInAddress.toLowerCase() !== newAccount.toLowerCase()) {
      
      // 更新当前账户
      web3State.account = newAccount;
      web3State.isConnected = true;
      
      // 显示提示
      showDialog({
        title: '账户已切换',
        message: '检测到您切换了钱包账户，需要重新登录。是否立即登录？',
        confirmButtonText: '立即登录',
        cancelButtonText: '稍后登录',
        showCancelButton: true
      }).then(action => {
        if (action === 'confirm') {
          // 先登出再登录
          logoutWb3();
          login();
        }
      });
    } else {
      // 更新当前账户
      web3State.account = newAccount;
      web3State.isConnected = true;
    }
    
    // 获取当前链ID
    try {
      const chainId = await window.ethereum.request({ method: 'eth_chainId' });
      handleChainChanged(chainId);
    } catch (error) {
      console.error('获取链ID失败:', error);
    }
  }
};

/**
 * 处理链变化
 * @param {string} chainId 链ID
 */
const handleChainChanged = (chainId) => {
  // 将十六进制转换为十进制
  const chainIdDecimal = parseInt(chainId, 16);
  web3State.chainId = chainIdDecimal;
  
  // 更新网络名称
  if (networks[chainIdDecimal]) {
    web3State.networkName = networks[chainIdDecimal].name;
  } else {
    web3State.networkName = `未知网络 (ID: ${chainIdDecimal})`;
  }
  
  //TODO: xxxx
  //showToast(`网络已切换到: ${web3State.networkName} 需要切换到正确的网络！！！！`);
  
  // 当链变化时，重新获取余额
  // if (web3State.account) {
  //   window.ethereum.request({
  //     method: 'eth_getBalance',
  //     params: [web3State.account, 'latest']
  //   }).then(balance => {
  //     const etherValue = parseInt(balance, 16) / 1e18;
  //     web3State.balance = etherValue.toFixed(4);
  //   }).catch(error => {
  //     console.error('获取余额失败:', error);
  //   });
  // }
};

/**
 * 处理连接事件
 * @param {Object} connectInfo 连接信息
 */
const handleConnect = (connectInfo) => {
  console.log('MetaMask连接成功:', connectInfo);
};

/**
 * 处理断开连接事件
 * @param {Object} error 错误信息
 */
const handleDisconnect = (error) => {
  console.log('MetaMask断开连接:', error);
  web3State.isConnected = false;
  web3State.account = '';
  showToast('钱包已断开连接');
};

/**
 * 连接钱包
 * @returns {Promise<string>} 连接的账户地址
 */
const connectWallet = async () => {
  try {
    if (!checkIfMetaMaskInstalled()) {
      showDialog({
        title: '未检测到钱包',
        message: '您需要安装MetaMask钱包来使用此功能。是否前往安装？',
        confirmButtonText: '前往安装',
        cancelButtonText: '取消',
        showCancelButton: true
      }).then(action => {
        if (action === 'confirm') {
          window.open('https://metamask.io/download.html', '_blank');
        }
      });
      return null;
    }

    // 请求用户连接
    const accounts = await window.ethereum.request({ 
      method: 'eth_requestAccounts' 
    });
    
    handleAccountsChanged(accounts);
    return accounts[0];
  } catch (error) {
    if (error.code === 4001) {
      // 用户拒绝了请求
      showToast(errorMessages.userRejected);
    } else {
      showToast(errorMessages.connectionFailed);
      console.error('连接钱包失败:', error);
    }
    return null;
  }
};

/**
 * 断开钱包连接
 * 注意：MetaMask实际上不支持通过API断开连接，
 * 这个函数只是清除本地状态
 */
const disconnectWallet = () => {
  web3State.isConnected = false;
  web3State.account = '';
  showToast('已断开钱包连接状态');
};

/**
 * 签名消息
 * @param {string} message ,timestamp 要签名的消息
 * @returns {Promise<string>} 签名结果
 */
const signMessage = async (msg,timestamp) => {
  try {
    if (!web3State.isConnected) {
      await connectWallet();
      if (!web3State.isConnected) return null;
    }

    const from = web3State.account;
    const msgParams = JSON.stringify({
      domain: {
        name: '我的DApp',
        version: '1',
        chainId: web3State.chainId,
      },
      message: {
        contents: msg,
        timestamp: timestamp,
      },
      primaryType: 'Message',
      types: {
        EIP712Domain: [
          { name: 'name', type: 'string' },
          { name: 'version', type: 'string' },
          { name: 'chainId', type: 'uint256' },
        ],
        Message: [
          { name: 'contents', type: 'string' },
          { name: 'timestamp', type: 'uint256' },
        ],
      },
    });
    //console.log('msgParams:', msgParams)
    const signature = await window.ethereum.request({
      method: 'eth_signTypedData_v4',
      params: [from, msgParams],
      from,
    });

    return signature;
  } catch (error) {
    if (error.code === 4001) {
      showToast('用户拒绝了签名请求');
    } else {
      showToast(errorMessages.signFailed);
      console.error('签名失败:', error);
    }
    return null;
  }
};

/**
 * 用户登录
 * 连接钱包并请求签名以验证用户身份
 * @returns {Promise<boolean>} 登录是否成功
 */
const login = async () => {
  try {
    // 首先连接钱包
    const account = await connectWallet();
    if (!account) {
      return false;
    }

    console.log('开始获取nonce，当前环境变量：', import.meta.env.VITE_API_MOCK, import.meta.env.VITE_API_BASE_URL);
    
    // 获取nonce信息
    const nonceResponse = await user.nonce({
      typ: 'login',
      address: account
    });
    
    
    if (nonceResponse.code !== 0 || !nonceResponse.data) {
      showToast('获取登录信息失败');
      return false;
    }
    
    const { nonce: nonceValue, tips } = nonceResponse.data;
    let timestamp = new Date().getTime()+"";
    
    // 构建签名消息
    showToast('请在钱包中确认签名');
    const signature = await signMessage(tips,timestamp);
    
    if (!signature) {
      showToast('签名失败，登录取消');
      return false;
    }

    console.log('开始调用登录API',account,tips,signature);
    
    // 调用登录API
    const loginResponse = await user.login({
      address: account,
      nonce: nonceValue,
      timestamp: timestamp,
      chainId: web3State.chainId,
      message: tips,
      signature
    });
    
    console.log('登录响应:', loginResponse);
    
    if (loginResponse.code !== 0 || !loginResponse.data || !loginResponse.data.token) {
      showToast('登录失败: ' + (loginResponse.message || '未知错误'));
      return false;
    }
    
    // 保存用户信息（只包含address和token）
    const userInfo = {
      address: account,
      token: loginResponse.data.token
    };
    
    // 只在 sessionManager 中保存用户信息，不在 web3State 中保存

    saveUserInfo(userInfo);
    
    showToast('登录成功');
    return true;
  } catch (error) {
    console.error('登录失败:', error);
    showToast('登录失败');
    return false;
  }
};

/**
 * 用户登出
 * @param {boolean} silent 是否静默登出（不显示提示和跳转）
 */
const logoutWb3 = async (silent = false) => {
  try {
    // 调用登出API
    if (checkLoginStatus()) {
      await user.logout();
    }
  } catch (error) {
    console.error('登出API调用失败:', error);
  } finally {
    // 清除本地会话
    clearSession();
    
    if (!silent) {
      //showToast('已退出登录');
      
      // 跳转到首页
      router.push('/home');
    }
  }
};

/**
 * 检查用户是否已登录
 * @returns {boolean} 是否已登录
 */
const isLoggedIn = () => {
  // 直接从会话管理器检查登录状态
  return checkLoginStatus();
};

/**
 * 发送交易
 * @param {Object} txParams 交易参数
 * @returns {Promise<string>} 交易哈希
 */
const sendTransaction = async (txParams) => {
  try {
    if (!web3State.isConnected) {
      await connectWallet();
      if (!web3State.isConnected) return null;
    }

    // 确保交易参数包含from地址
    const params = {
      from: web3State.account,
      ...txParams
    };

    // 发送交易
    const txHash = await window.ethereum.request({
      method: 'eth_sendTransaction',
      params: [params],
    });

    showToast('交易已提交');
    return txHash;
  } catch (error) {
    if (error.code === 4001) {
      showToast('用户拒绝了交易请求');
    } else {
      showToast(errorMessages.transactionFailed);
      console.error('交易失败:', error);
    }
    return null;
  }
};

/**
 * 切换网络
 * @param {number} chainId 目标链ID
 * @returns {Promise<boolean>} 是否成功切换
 */
const switchNetwork = async (chainId) => {
  try {
    await window.ethereum.request({
      method: 'wallet_switchEthereumChain',
      params: [{ chainId: `0x${chainId.toString(16)}` }],
    });
    return true;
  } catch (error) {
    // 如果链不存在，可能需要添加
    if (error.code === 4902) {
      showToast('该网络不存在，请先添加网络');
    } else if (error.code === 4001) {
      showToast('用户拒绝了切换网络请求');
    } else {
      showToast('切换网络失败');
      console.error('切换网络失败:', error);
    }
    return false;
  }
};

/**
 * 添加网络
 * @param {Object} networkParams 网络参数
 * @returns {Promise<boolean>} 是否成功添加
 */
const addNetwork = async (networkParams) => {
  try {
    await window.ethereum.request({
      method: 'wallet_addEthereumChain',
      params: [networkParams],
    });
    return true;
  } catch (error) {
    if (error.code === 4001) {
      showToast('用户拒绝了添加网络请求');
    } else {
      showToast('添加网络失败');
      console.error('添加网络失败:', error);
    }
    return false;
  }
};

/**
 * 添加代币
 * @param {Object} tokenParams 代币参数
 * @returns {Promise<boolean>} 是否成功添加
 */
const addToken = async (tokenParams) => {
  try {
    await window.ethereum.request({
      method: 'wallet_watchAsset',
      params: {
        type: 'ERC20',
        options: tokenParams,
      },
    });
    return true;
  } catch (error) {
    if (error.code === 4001) {
      showToast('用户拒绝了添加代币请求');
    } else {
      showToast('添加代币失败');
      console.error('添加代币失败:', error);
    }
    return false;
  }
};

/**
 * 获取交易收据
 * @param {string} txHash 交易哈希
 * @returns {Promise<Object>} 交易收据
 */
const getTransactionReceipt = async (txHash) => {
  try {
    const receipt = await window.ethereum.request({
      method: 'eth_getTransactionReceipt',
      params: [txHash],
    });
    return receipt;
  } catch (error) {
    console.error('获取交易收据失败:', error);
    return null;
  }
};

/**
 * 自动连接钱包
 * 在应用启动时调用
 */
const autoConnectWallet = async () => {
  const initialized = await initWeb3();
  if (initialized) {
    // 如果已经连接，不需要再次连接
    if (web3State.isConnected) return;
    
    // 尝试静默连接钱包
    try {
      // 首先尝试获取已连接的账户，这不会弹出钱包请求
      const accounts = await window.ethereum.request({ 
        method: 'eth_accounts'
      });
      
      if (accounts.length > 0) {
        // 如果有已连接的账户，更新状态
        web3State.account = accounts[0];
        web3State.isConnected = true;
        
        // 获取链ID
        const chainId = await window.ethereum.request({ method: 'eth_chainId' });
        handleChainChanged(chainId);
        
        // 检查钱包地址是否与登录地址匹配
        const isUserLoggedIn = checkLoginStatus();
        const loggedInAddress = getUserAddress();
        
        if (isUserLoggedIn && loggedInAddress && loggedInAddress.toLowerCase() !== accounts[0].toLowerCase()) {
          console.warn('钱包地址与登录地址不匹配，可能需要重新登录');
        }
        
        return;
      }
      
      // 如果没有已连接的账户，尝试请求连接（这可能会弹出钱包请求）
      // 但我们使用静默模式，避免在页面加载时打扰用户
      const requestedAccounts = await window.ethereum.request({ 
        method: 'eth_requestAccounts',
        params: [{ eth_accounts: {} }]
      });
      
      if (requestedAccounts.length > 0) {
        web3State.account = requestedAccounts[0];
        web3State.isConnected = true;
        
        // 获取链ID
        const chainId = await window.ethereum.request({ method: 'eth_chainId' });
        handleChainChanged(chainId);
      }
    } catch (error) {
      // 静默失败，不显示错误
      console.log('自动连接钱包失败，等待用户手动连接', error);
    }
  }
};

// 导出所有方法和状态
export {
  web3State,
  initWeb3,
  connectWallet,
  disconnectWallet,
  signMessage,
  sendTransaction,
  switchNetwork,
  addNetwork,
  addToken,
  getTransactionReceipt,
  autoConnectWallet,
  checkIfMetaMaskInstalled,
  login,
  logoutWb3,
  isLoggedIn
};
